package demo.android.com.mvpdemo.myRetrofit;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import okhttp3.OkHttpClient;

/**
 * Created by Vya on 2018/2/2 0002.
 */

public class Retrofit {
    final String baseUrl;
    final okhttp3.Call.Factory callFactory;
    private Map<Method,ServiceMethod> serviceMethodMapCache = new ConcurrentHashMap<>();

    public Retrofit(Builder builder) {
        this.baseUrl = builder.baseUrl;
        this.callFactory = builder.callFactory;
    }

    public <T> T create(Class<T> service) {
        //动态代理创建
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //每执行一个方法都会来这里

                //如果当前是调用的Object的方法就不要往下执行了
                if(method.getDeclaringClass() == Object.class){
                    return method.invoke(this,args); //一般来说这里应该是使用策略模式选择合适的策略来执行
                }

                //解析参数的注解
                ServiceMethod serviceMethod = loadServiceMethod(method);

                //封装OkHttpCall
                OkHttpCall okHttpCall = new OkHttpCall(serviceMethod,args);
                return okHttpCall;
            }
        });
    }


    private ServiceMethod loadServiceMethod(Method method) {
        //享元设计模式  共享对象
        ServiceMethod serviceMethod = serviceMethodMapCache.get(method);
        if(null == serviceMethod){
            serviceMethod = new ServiceMethod.Builder(this,method).build();
            serviceMethodMapCache.put(method,serviceMethod);
        }
        return null;

    }

    public static class Builder{
        private String baseUrl;
        okhttp3.Call.Factory callFactory;
        public Builder baseUrl(String baseUrl){
            this.baseUrl = baseUrl;
            return this;
        }

        public Builder client(okhttp3.Call.Factory callFactory) {
            this.callFactory = callFactory;
            return this;
        }

        public Retrofit build() {
            if(null == callFactory){
                callFactory = new OkHttpClient();
            }
            return new Retrofit(this);
        }
    }
}
